﻿using System;
using System.Text;
using System.Collections.Generic;
using BerkeleyDB;
using System.Data.SQLite;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using System.Collections;
using System.Data;
namespace DelicateDict.Classes
{
    class DictType
    {
        bool DBDefault;
        string DBName;
        string DBPath;
        string WordList;
        public static ushort DBCount = 0;
        public DictType()
        {
            this.DBDefault = false;        
            this.DBName = null;
            this.DBPath = null;
            this.WordList = null;
            ++DBCount;
        }
        public DictType(bool DF,string _dbName, string _dbPath, string wordlist)
        {
            this.DBDefault = DF;        
            this.DBName = _dbName;
            this.DBPath = _dbPath;
            this.WordList = wordlist;
            DBCount++;
        }
        public bool IsDefault
        {
            set { DBDefault = value; }
            get { return DBDefault; }
        }
      
        public string DbName
        {
            set { DBName = value; }
            get { return DBName; }
        }
        public string DbPath
        {
            set { DBPath = value; }
            get { return DBPath; }
        }
        public string DBWord
        {
            set { WordList = value; }
            get { return WordList; }
        }
        public ushort Count
        {
            get { return DBCount; }
        }      
    }
    public class ArrayOfDictType : IEnumerable
    {
        DictType[] dt;
        public ArrayOfDictType(int num)
        {
            dt = new DictType[num];
            for (int i = 0; i < num; i++)
            {
                dt[i] = new DictType();
            }
        }
        public IEnumerator GetEnumerator()
        {
            return new Iterator(this);
        }
        public class Iterator : IEnumerator
        {
            ArrayOfDictType AODT;
            short position = -1;
            public Iterator(ArrayOfDictType aodt)
            {
                AODT = aodt;
            }
            public void Reset()
            {
                position = -1;
            }
            public bool MoveNext()
            {
                position++;
                return (position < AODT.dt.Length);  
            }
            public object Current
            {
                get { return AODT.dt[position];}
            }

        }
    }

    class _Database
    {
        DictType dicttype;
        private BTreeDatabaseConfig btreeDBCfg;
        public static BTreeDatabase btreeDB;

        public _Database()
        {
            IOFile iof = new IOFile();
            string[] defaultDictType = iof.Read_DefaultDatabae().Split(';');
            dicttype = new DictType(Convert.ToBoolean(defaultDictType[0]), defaultDictType[1], defaultDictType[2], defaultDictType[3]);
            ReadDatabase();
           // Open();
        }
        public _Database(DictType dt)
        {
            this.dicttype = dt;
            ReadDatabase();
        }
       
        public bool ReadDatabase()
        {
            btreeDBCfg = new BTreeDatabaseConfig();
           // btreeDBCfg.CacheSize = new CacheInfo(0, 64 * 1024, 1);
            //btreeDBCfg.PageSize = 8 * 1024;
           //btreeDBCfg.Duplicates = DuplicatesPolicy.NONE;
           // btreeDBCfg.FreeThreaded = true;
            try
            {
                btreeDB = BTreeDatabase.Open(dicttype.DbPath, btreeDBCfg);
            }
            catch (DatabaseException e)
            {
                MessageBox.Show("Loading Database error: " + e.ToString());
                return false;
            }
            return true;
        }

        /*~_Database()
        {
            dicttype = null;
            btreeDB.Close();
        }*/
        public void CloseDatabase()
        {
            dicttype = null;
            btreeDBCfg = null;
            //btreeDB.Close();
        }
        public string GetMean(string word)
        {
            
            DatabaseEntry key = new DatabaseEntry();
           // key.Data = Encoding.UTF8.GetBytes(word);
            SetDataEntry(ref key,word);
            try
            {
                KeyValuePair<DatabaseEntry, DatabaseEntry> pair = btreeDB.Get(key);
                btreeDB.Close();
                return GetDataEntry(pair.Value);
            }
            catch (NotFoundException e)
            {
                btreeDB.Close();
                return e.Message;
            }
        }
        public static string GetMean(string word, DictType dt)
        {

            BTreeDatabase dbt = null;
            BTreeDatabaseConfig DBcfg = new BTreeDatabaseConfig();

            try
            {
                dbt = BTreeDatabase.Open(dt.DbPath, DBcfg);
            }
            catch (DatabaseException e)
            {
                MessageBox.Show(e.ToString());
            }
            DatabaseEntry key = new DatabaseEntry(Encoding.UTF8.GetBytes(word));
            try
            {
                KeyValuePair<DatabaseEntry, DatabaseEntry> pair = dbt.Get(key);
                //return GetDataEntry(pair.Value);
                return Encoding.UTF8.GetString(pair.Value.Data);
            }
            catch (NotFoundException)
            {
                return "Word Not Found !";
            }
            
        }
        public bool Data_Delete(string word)
        {
              
            DatabaseEntry key = new DatabaseEntry(Encoding.UTF8.GetBytes(word));
            try
            {
               //dbt.Delete(key);
                btreeDB.Delete(key);
                btreeDB.Close();
            }
            catch (NotFoundException)
            { 
                 MessageBox.Show("Word Not Found");
                 btreeDB.Close();
                return false;
            }
          
            return true;
        }
        public bool Data_Update(string word,string mean)
        {
            DatabaseEntry key = new DatabaseEntry(Encoding.UTF8.GetBytes(word));
            DatabaseEntry value = new DatabaseEntry(Encoding.UTF8.GetBytes(mean));

            try
            {
               //dbt.Put(key,value);
                btreeDB.Put(key, value);
                btreeDB.Close();
            }
            catch (DatabaseException e)
            {
               MessageBox.Show("Error :"+e.ToString());
               btreeDB.Close();
                return false;
            }
          
            return true;
        }

        //
        public bool Data_Insert(string word,string mean)
        {
           
        
            DatabaseEntry key = new DatabaseEntry(Encoding.UTF8.GetBytes(word));       
            DatabaseEntry value = new DatabaseEntry(Encoding.UTF8.GetBytes(mean));
            try
            {
               btreeDB.PutNoOverwrite(key,value);
               btreeDB.Close();
            }
            catch (DatabaseException e)
            {  
                 MessageBox.Show("Error :"+e.ToString());
                btreeDB.Close();
                return false;
            }
            return true;
        }

        //
        public DictType DictionaryType
        {
            set { dicttype = value; }
            get { return dicttype; }
        }
        public bool CheckKeyExist(string word)
        {
            DatabaseEntry key = new DatabaseEntry(Encoding.UTF8.GetBytes(word));
               return btreeDB.Exists(key);
      
        }
       // public bool Data_Edit(string edit
        private void SetDataEntry(ref DatabaseEntry key, string data)
        {
            key.Data = Encoding.UTF8.GetBytes(data);
        }
        private string GetDataEntry(DatabaseEntry key)
        {
            return Encoding.UTF8.GetString(key.Data);
        }
      
    }
    class SQLiteDB
    {
        SQLiteConnection conn;
        SQLiteCommand cmd;
        string ConnectString = @"Data Source=mystudy.db";
        public SQLiteDB() 
        {
            conn = new SQLiteConnection(ConnectString);
        }
        ~SQLiteDB()
        {
            conn.Close();
        }
        public bool Insert(string word, string mean,string dicttype)
        {
            string SqlQuery = @"INSERT INTO mystudy VALUES (@word,@mean,@dicttype,date('now'))";
            cmd = new SQLiteCommand(SqlQuery, conn);
            cmd.Parameters.Add("@word", System.Data.DbType.String);
            cmd.Parameters.Add("@mean", System.Data.DbType.String);
            cmd.Parameters.Add("@dicttype", System.Data.DbType.String);
            try
            {
                conn.Open();
                cmd.Parameters["@word"].Value = word;
                cmd.Parameters["@mean"].Value = mean;
                cmd.Parameters["@dicttype"].Value = dicttype;
                cmd.ExecuteNonQuery();
                return true;
            }
            catch
            {
                return false;
            }
          
        }
        public string SelecMean(string word)
        {
            string SqlQuery = @"SELECT mean From mystudy WHERE word = @word";
            cmd = new SQLiteCommand(SqlQuery, conn);
            cmd.Parameters.Add("@word", DbType.String);
            cmd.Parameters["@word"].Value = word;
            return (string)cmd.ExecuteScalar();
        }
        public DataTable SelectWords(string month)

        {
            
            string SqlQuery = @"SELECT word as Words FROM mystudy WHERE strftime('%m-%Y'
,date) = @month";
            cmd = new SQLiteCommand(SqlQuery,conn);
            cmd.Parameters.Add("@month",DbType.String);
            cmd.Parameters["@month"].Value = month;
            try
            {
                conn = new SQLiteConnection(ConnectString);
                conn.Open();
                SQLiteDataAdapter da = new SQLiteDataAdapter(cmd);
                DataSet ds = new DataSet();
                da.Fill(ds, "mystudy");
                DataTable dt = ds.Tables["mystudy"];
                return dt;

            }
            catch
            {

                return null;
            }      
        }
        public DataTable SelectSum()
        {
            string SqlQuery = @"SELECT strftime('%m-%Y',date) as 'Month-Year',count(word) as 'Total' FROM mystudy GROUP BY strftime('%m-%Y',date)";
            try
            {
                conn.Open();
                SQLiteDataAdapter da = new SQLiteDataAdapter(SqlQuery, conn);
                DataSet ds = new DataSet();
                da.Fill(ds,"mystudy");
                DataTable dt = ds.Tables["mystudy"];
                return dt;
               
            }
            catch
            {
                
                return null;
            }      
        }
        public bool Delete(string word)
        {
            string SqlQuery = "DELETE FROM mystudy WHERE word= @word";
            cmd = new SQLiteCommand(SqlQuery, conn);
            cmd.Parameters.Add("@word", DbType.String);
            cmd.Parameters["@word"].Value = word;
            try
            {
                conn = new SQLiteConnection(ConnectString);
                conn.Open();
                cmd.ExecuteNonQuery();
                return true;
            }
            catch
            {
                return false;
            }
        }
        public bool DeleteMonth(string word)
        {
            string SqlQuery = "DELETE FROM mystudy WHERE strftime('%m-%Y',date) = (SELECT strftime('%m-%Y',date) FROM mystudy WHERE word =@word)";
            cmd = new SQLiteCommand(SqlQuery, conn);
            cmd.Parameters.Add("@word", DbType.String);
            cmd.Parameters["@word"].Value = word;
            try
            {
                conn = new SQLiteConnection(ConnectString);
                conn.Open();
                cmd.ExecuteNonQuery();
                return true;
            }
            catch
            {
                return false;
            }
        }
        public bool DeleteAll()
        {
            string SqlQuery = "DELETE FROM mystudy";
            cmd = new SQLiteCommand(SqlQuery, conn);
            try
            {
                conn = new SQLiteConnection(ConnectString);
                conn.Open();
                cmd.ExecuteNonQuery();
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}
